-- Boolean.hs
import Prelude hiding (and, not, or, (&&), (/=), (==), (||))

-- --
(==) :: Bool -> Bool -> Bool
(==) True True = True
(==) False False = True
(==) _ _ = False

--
not :: Bool -> Bool
not True = False
not _ = True

--
not'' = (== False)

xor, and, or :: Bool -> Bool -> Bool
xor b1 b2 = not (b1 == b2)
and True b1 = b1
and False _ = False
or False b1 = b1
or True _ = True

infix 4 ==

infix 4 /=

infixl 3 &&

infixl 2 ||

(||) = or

(&&) = and

(/=) = xor

-- half adder
hA :: Bool -> Bool -> (Bool, Bool)
hA a b = (a /= b, a && b)

-- full adder
fA a b c = (axbxc, aab || axbac)
  where
    (axb, aab) = hA a b
    (axbxc, axbac) = hA axb c

-- 与⾮⻔和或⾮⻔
nand, nor :: Bool -> Bool -> Bool
nand True True = False
nand _ _ = True
nor False False = True
nor _ _ = False

-- not
not1, not2 :: Bool -> Bool
not1 b = nand b b
not2 b = nor b b

-- and
and1, and2 :: Bool -> Bool -> Bool
-- and1 b1 b2 = not1 $ nand b1 b2
and1 b1 b2 = nand (nand b1 b2) (nand b1 b2)
-- and2 b1 b2 = nor (not2 b1) (not2 b2)
and2 b1 b2 = nor (nor b1 b1) (nor b2 b2)

-- or
or1, or2 :: Bool -> Bool -> Bool
-- or1 b1 b2 = nand (not1 b1) (not1 b2)
or1 b1 b2 = nand (nand b1 b1) (nand b2 b2)
-- or2 b1 b2 = not2 $ nor b1 b2
or2 b1 b2 = nor (nor b1 b2) (nor b1 b2)

-- nor, nand 互相定义
nor2 :: Bool -> Bool -> Bool
nor2 b1 b2 = nand b b
  where
    b = nand (nand b1 b1) (nand b2 b2)

nand2 :: Bool -> Bool -> Bool
nand2 b1 b2 = nor a1 a2
  where
    a1 = nor b1 b1
    a2 = nor b2 b2

xor1 :: Bool -> Bool -> Bool
-- xor1 b1 b2 = or1 (and1 b1 (not1 b2)) (and1 (not1 b1) b2)
-- xor1 b1 b2 = nand (not1 (and1 b1 (not1 b2)) (not1 (and1 (not1 b1) b2)
-- xor1 b1 b2 = nand (nand b1 (nand b1 b2)) (nand b2 (nand b1 b2))
xor1 b1 b2 = nand (nand b1 nb1b2) (nand b2 nb1b2)
  where
    nb1b2 = nand b1 b2